package com.jfireframework.commonloggersolution;

import com.jfireframework.baseutil.TRACEID;
import sun.util.locale.LanguageTag;

import java.nio.ByteBuffer;

public class CycleBuffer
{
    ByteBuffer buffer;
    volatile int start;
    volatile int end;
    BufferMode mode;

    public CycleBuffer(ByteBuffer buffer, int start, int end, BufferMode mode)
    {
        String traceId = TRACEID.currentTraceId();
        this.buffer = buffer;
        this.mode = mode;
        resetStartAndEnd(start, end);
    }

    public void resetStartAndEnd(int start, int end)
    {
        if (start > end)
        {
            CommonFileLoggerImpl.LOGGER.debug("traceId:{} 设置Buffer的起止位置，buffer的实际开始位置是:{},实际结束位置是:{}。该Buffer为{}模式", TRACEID.currentTraceId(), start, end, mode);
            buffer.limit(buffer.capacity()).position(start);
        }
        else
        {
            CommonFileLoggerImpl.LOGGER.debug("traceId:{} 设置Buffer的起止位置，buffer的实际开始位置是:{},实际结束位置是:{}。该Buffer为{}模式", TRACEID.currentTraceId(), start, end, mode);
            buffer.limit(end).position(start);
        }
        this.start = start;
        this.end = end;
    }

    public byte get()
    {
        if (mode == BufferMode.write)
        {
            throw new IllegalStateException("模式错误");
        }
        if (remaining() < 1)
        {
            throw new IllegalStateException();
        }
        return buffer.get();
    }

    public long getLong()
    {
        if (mode == BufferMode.write)
        {
            throw new IllegalStateException("模式错误");
        }
        if (remaining() < 8)
        {
            throw new IllegalStateException();
        }
        if (start < end)
        {
            return buffer.getLong();
        }
        else
        {
            if (buffer.remaining() >= 8)
            {
                return buffer.getLong();
            }
            else
            {
                int  left   = buffer.remaining();
                long result = 0;
                for (int i = 0; i < left; i++)
                {
                    result |= (buffer.get() & 0xffffffffL) << (56 - i * 8);
                }
                buffer.position(0).limit(end);
                for (int i = left; i < 8; i++)
                {
                    result |= (buffer.get() & 0xffffffffL) << (56 - i * 8);
                }
                return result;
            }
        }
    }

    public void get(byte[] value)
    {
        if (mode == BufferMode.write)
        {
            throw new IllegalStateException("模式错误");
        }
        if (remaining() < value.length)
        {
            throw new IllegalStateException();
        }
        if (buffer.remaining() >= value.length)
        {
            buffer.get(value);
            return;
        }
        int left = buffer.remaining();
        buffer.get(value, 0, left);
        buffer.position(0).limit(end);
        buffer.get(value, left, value.length - left);
    }

    public int remaining()
    {
        if (start <= end)
        {
            return buffer.remaining();
        }
        else
        {
            if (start > end && buffer.position() == buffer.capacity())
            {
                buffer.position(0).limit(end);
                return buffer.remaining();
            }
            if (buffer.position() > end)
            {
                return buffer.remaining() + end;
            }
            else
            {
                return buffer.remaining();
            }
        }
    }

    public short getShort()
    {
        if (mode == BufferMode.write)
        {
            throw new IllegalStateException("模式错误");
        }
        if (remaining() < 2)
        {
            throw new IllegalStateException();
        }
        if (buffer.remaining() >= 2)
        {
            return buffer.getShort();
        }
        else
        {
            short result = 0;
            result |= (buffer.get() & 0xff) << 8;
            buffer.position(0).limit(end);
            result |= (buffer.get() & 0xff);
            return result;
        }
    }

    public int getInt()
    {
        if (mode == BufferMode.write)
        {
            throw new IllegalStateException("模式错误");
        }
        if (remaining() < 4)
        {
            throw new IllegalStateException();
        }
        if (buffer.remaining() >= 4)
        {
            return buffer.getInt();
        }
        else
        {
            int remaining = buffer.remaining();
            int result    = 0;
            for (int i = 0; i < remaining; i++)
            {
                result |= (buffer.get() & 0xff) << (32 - i * 8);
            }
            buffer.position(0).limit(end);
            for (int i = remaining; i < 4; i++)
            {
                result |= (buffer.get() & 0xff) << (32 - i * 8);
            }
            return result;
        }
    }

    public void put(byte value)
    {
        if (mode == BufferMode.read)
        {
            throw new IllegalStateException("模式错误");
        }
        if (remaining() < 1)
        {
            throw new IllegalStateException();
        }
        buffer.put(value);
    }

    public void putLong(long value)
    {
        if (mode == BufferMode.read)
        {
            throw new IllegalStateException("模式错误");
        }
        if (remaining() < 8)
        {
            throw new IllegalStateException();
        }
        if (buffer.remaining() >= 8)
        {
            buffer.putLong(value);
        }
        else
        {
            int remaining = buffer.remaining();
            for (int i = 0; i < remaining; i++)
            {
                buffer.put((byte) ((value >>> (56 - 8 * i) & 0xff)));
            }
            buffer.position(0).limit(end);
            for (int i = remaining; i < 8; i++)
            {
                buffer.put((byte) ((value >>> (56 - 8 * i) & 0xff)));
            }
        }
    }

    public void putShort(short value)
    {
        if (mode == BufferMode.read)
        {
            throw new IllegalStateException("模式错误");
        }
        if (buffer.remaining() >= 2)
        {
            buffer.putShort(value);
        }
        else
        {
            //具备足够的写入空间，但是当前buffer剩余小于2.这意味着当前剩余必然为1
            buffer.put((byte) (value >>> 8));
            buffer.position(0).limit(end);
            buffer.put((byte) value);
        }
    }

    public void putInt(int value)
    {
        if (mode == BufferMode.read)
        {
            throw new IllegalStateException("模式错误");
        }
        if (buffer.remaining() >= 4)
        {
            buffer.putInt(value);
        }
        else
        {
            int remaining = buffer.remaining();
            for (int i = 0; i < remaining; i++)
            {
                buffer.put((byte) ((value >>> (24 - 8 * i) & 0xff)));
            }
            buffer.position(0).limit(end);
            for (int i = remaining; i < 4; i++)
            {
                buffer.put((byte) ((value >>> (24 - 8 * i) & 0xff)));
            }
        }
    }

    public void put(byte[] value)
    {
        if (mode == BufferMode.read)
        {
            throw new IllegalStateException("模式错误");
        }
        if (remaining() < value.length)
        {
            throw new IllegalStateException();
        }
        else
        {
            if (buffer.remaining() >= value.length)
            {
                buffer.put(value);
            }
            else
            {
                int remaining = buffer.remaining();
                buffer.put(value, 0, remaining);
                buffer.position(0).limit(end);
                buffer.put(value, remaining, value.length - remaining);
            }
        }
    }
}
